#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/io.h>
#include <uapi/linux/fs.h>
#include <linux/kthread.h>
#include <linux/timer.h>
#include <linux/timekeeping.h>
#include <linux/jiffies.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/string.h>
#include <linux/sprintf.h>
#include <linux/kstrtox.h>
#include <linux/proc_fs.h>
#include <linux/kobject.h>
#include <linux/device/class.h>
#include <linux/device.h>
#include <linux/fcntl.h>

#include "custom_module_uapi.h"

#define CUSTOM_MODULE_STR_LEN 128
#define CUSTOM_MODULE_PAUSE_DELAY_MS 1000

struct proc_data {
    struct proc_dir_entry *proc_dir;
    struct proc_dir_entry *memory_size_proc_file;
    struct proc_dir_entry *running_delayms_proc_file;
    struct proc_dir_entry *timer_step_proc_file;
    struct proc_dir_entry *poll_maxsize_proc_file;
};

typedef struct {
    int major;
    char *module_name;
    char *memory;
    unsigned long long memory_size;
    bool isStartTimer;
    bool isPauseControlThread;
    struct task_struct *control_thread;
    struct timer_list timer;
    wait_queue_head_t waitqueue_poll;
    wait_queue_head_t waitqueue_timer;
    unsigned int running_delayms;
    unsigned int timer_step;
    unsigned int poll_maxsize;
    struct proc_data proc;
    struct kobject *kobject;
    struct class *class;
    struct device *device;
    struct fasync_struct *fapp;
} custom_module_data;

static custom_module_data g_private_data = {
    .module_name = "custom_module",
};

/* sysfs start */
static ssize_t custom_module_memorysize_show(struct kobject *obj, struct kobj_attribute *attr, char *buf)
{
    return sprintf(buf, "%llu\n", g_private_data.memory_size);
}

static struct kobj_attribute memorysize_sysfs_ops = __ATTR(memory_size, 0644, custom_module_memorysize_show, NULL);

static ssize_t custom_module_running_delayms_show(struct kobject *obj, struct kobj_attribute *attr, char *buf)
{
    return sprintf(buf, "%u\n", g_private_data.running_delayms);
}

static ssize_t custom_module_running_delayms_store(struct kobject *obj, struct kobj_attribute *attr, const char *buf, size_t count)
{
    unsigned long res;
    int ret = kstrtoul(buf, 10, &res);
    if (ret == -ERANGE) {
        printk(KERN_ERR "[%s][%d]str %s overflow\n", __func__, __LINE__, buf);
    } else if (ret == -EINVAL) {
        printk(KERN_ERR "[%s][%d]str %s parsing error\n", __func__, __LINE__, buf);
    } else {
        g_private_data.running_delayms = res;
    }
    return count;
}

static struct kobj_attribute running_delayms_sysfs_ops = __ATTR(running_delayms, 0644, custom_module_running_delayms_show, custom_module_running_delayms_store);

static ssize_t custom_module_timer_step_show(struct kobject *obj, struct kobj_attribute *attr, char *buf)
{
    return sprintf(buf, "%u\n", g_private_data.timer_step);
}

static ssize_t custom_module_timer_step_store(struct kobject *obj, struct kobj_attribute *attr, const char *buf, size_t count)
{
    unsigned long res;
    int ret = kstrtoul(buf, 10, &res);
    if (ret == -ERANGE) {
        printk(KERN_ERR "[%s][%d]str %s overflow\n", __func__, __LINE__, buf);
    } else if (ret == -EINVAL) {
        printk(KERN_ERR "[%s][%d]str %s parsing error\n", __func__, __LINE__, buf);
    } else {
        g_private_data.timer_step = res;
    }
    return count;
}

static struct kobj_attribute timer_step_sysfs_ops = __ATTR(timer_stepms, 0644, custom_module_timer_step_show, custom_module_timer_step_store);

static ssize_t custom_module_poll_maxsize_show(struct kobject *obj, struct kobj_attribute *attr, char *buf)
{
    return sprintf(buf, "%u\n", g_private_data.poll_maxsize);
}

static ssize_t custom_module_poll_maxsize_store(struct kobject *obj, struct kobj_attribute *attr, const char *buf, size_t count)
{
    unsigned long res;
    int ret = kstrtoul(buf, 10, &res);
    if (ret == -ERANGE) {
        printk(KERN_ERR "[%s][%d]str %s overflow\n", __func__, __LINE__, buf);
    } else if (ret == -EINVAL) {
        printk(KERN_ERR "[%s][%d]str %s parsing error\n", __func__, __LINE__, buf);
    } else {
        g_private_data.poll_maxsize = res;
    }
    return count;
}

static struct kobj_attribute poll_maxsize_sysfs_ops = __ATTR(poll_maxsize, 0644, custom_module_poll_maxsize_show, custom_module_poll_maxsize_store);

static int custom_module_sysfs_create(void)
{
    int ret;
    g_private_data.kobject = kobject_create_and_add(g_private_data.module_name, kernel_kobj);
    if (!g_private_data.kobject) {
        printk(KERN_ERR "[%s][%d]create sysfs %s failed\n", __func__, __LINE__, g_private_data.module_name);
        ret = -ENOENT;
        goto KOBJECT_CREATE_FAILED;
    }

    if (sysfs_create_file(g_private_data.kobject, &memorysize_sysfs_ops.attr)) {
        printk(KERN_ERR "[%s][%d]create sysfs %s failed\n", __func__, __LINE__, memorysize_sysfs_ops.attr.name);
        ret -ENOENT;
        goto MEMORYSIZE_SYSFS_CREATE_FAILED;
    }

    if (sysfs_create_file(g_private_data.kobject, &running_delayms_sysfs_ops.attr)) {
        printk(KERN_ERR "[%s][%d]create sysfs %s failed\n", __func__, __LINE__, running_delayms_sysfs_ops.attr.name);
        ret -ENOENT;
        goto RUNNING_DELAYMS_SYSFS_CREATE_FAILED;
    }

    if (sysfs_create_file(g_private_data.kobject, &timer_step_sysfs_ops.attr)) {
        printk(KERN_ERR "[%s][%d]create sysfs %s failed\n", __func__, __LINE__, timer_step_sysfs_ops.attr.name);
        ret -ENOENT;
        goto TIMER_STEP_SYSFS_CREATE_FAILED;
    }

    if (sysfs_create_file(g_private_data.kobject, &poll_maxsize_sysfs_ops.attr)) {
        printk(KERN_ERR "[%s][%d]create sysfs %s failed\n", __func__, __LINE__, poll_maxsize_sysfs_ops.attr.name);
        ret -ENOENT;
        goto POLL_MAXSIZE_DELAYMS_SYSFS_CREATE_FAILED;
    }
    return 0;
POLL_MAXSIZE_DELAYMS_SYSFS_CREATE_FAILED:
    sysfs_remove_file(g_private_data.kobject, &timer_step_sysfs_ops.attr);
TIMER_STEP_SYSFS_CREATE_FAILED:
    sysfs_remove_file(g_private_data.kobject, &running_delayms_sysfs_ops.attr);   
RUNNING_DELAYMS_SYSFS_CREATE_FAILED:
    sysfs_remove_file(g_private_data.kobject, &memorysize_sysfs_ops.attr);
MEMORYSIZE_SYSFS_CREATE_FAILED:
    kobject_put(g_private_data.kobject);
KOBJECT_CREATE_FAILED:
    return ret;
}

static void custom_module_sysfs_remove(void)
{
    sysfs_remove_file(g_private_data.kobject, &poll_maxsize_sysfs_ops.attr);
    sysfs_remove_file(g_private_data.kobject, &timer_step_sysfs_ops.attr);
    sysfs_remove_file(g_private_data.kobject, &running_delayms_sysfs_ops.attr);   
    sysfs_remove_file(g_private_data.kobject, &memorysize_sysfs_ops.attr);
    kobject_put(g_private_data.kobject);
}

/* sysfs end */

/* proc start */
static int custom_module_proc_open(struct inode *inode, struct file *file)
{
    printk("[%s][%d]\n", __func__, __LINE__);
    file->private_data = &g_private_data;
    return 0;
}

static int custom_module_proc_close(struct inode *node, struct file *file)
{
    printk("[%s][%d]\n", __func__, __LINE__);
    return 0;
}
// memorysize
static ssize_t custom_module_memorysize_proc_read(struct file *file, char __user *data, size_t len, loff_t *offset)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    char str[CUSTOM_MODULE_STR_LEN] = {0};
    int size = sprintf(str, "%llu\n", d->memory_size);
    // 需要对当前文件偏移做判断，因为cat命令会循环调用read直到返回0
    if (*offset >= size) {
        return 0;
    }
    int size_no_copy = copy_to_user(data, str, size);
    // 及时更新文件偏移值
    *offset += size - size_no_copy;
    return size - size_no_copy;
}

static struct proc_ops memorysize_proc_ops = {
    .proc_open = custom_module_proc_open,
    .proc_release = custom_module_proc_close,
    .proc_read = custom_module_memorysize_proc_read,
};
// running_delayms
static ssize_t custom_module_running_delayms_proc_read(struct file *file, char __user *data, size_t len, loff_t *offset)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    char str[CUSTOM_MODULE_STR_LEN] = {0};
    int size = sprintf(str, "%u\n", d->running_delayms);
    // 需要对当前文件偏移做判断，因为cat命令会循环调用read直到返回0
    if (*offset >= size) {
        return 0;
    }
    int size_no_copy = copy_to_user(data, str, size);
    // 及时更新文件偏移值
    *offset += size - size_no_copy;
    return size - size_no_copy;
}

static ssize_t custom_module_running_delayms_proc_write(struct file *file, const char __user *data, size_t len, loff_t *offset)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    char str[CUSTOM_MODULE_STR_LEN] = {0};
    int size_no_copy = copy_from_user(str, data, len);
    unsigned long res;
    int ret = kstrtoul(str, 10, &res);
    if (ret == -ERANGE) {
        printk(KERN_ERR "[%s][%d]str %s overflow\n", __func__, __LINE__, str);
    } else if (ret == -EINVAL) {
        printk(KERN_ERR "[%s][%d]str %s parsing error\n", __func__, __LINE__, str);
    } else {
        d->running_delayms = res;
    }
    *offset += len -size_no_copy;
    return len - size_no_copy;
}

static struct proc_ops running_delayms_proc_ops = {
    .proc_open = custom_module_proc_open,
    .proc_release = custom_module_proc_close,
    .proc_read = custom_module_running_delayms_proc_read,
    .proc_write = custom_module_running_delayms_proc_write,
}; 
// timer_step
static ssize_t custom_module_timer_step_proc_read(struct file *file, char __user *data, size_t len, loff_t *offset)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    char str[CUSTOM_MODULE_STR_LEN] = {0};
    int size = sprintf(str, "%u\n", d->timer_step);
    printk("[%s][%d] str=%s timer_step=%u size=%d\n", __func__, __LINE__, str, d->timer_step, size);
    // 需要对当前文件偏移做判断，因为cat命令会循环调用read直到返回0
    if (*offset >= size) {
        return 0;
    }
    int size_no_copy = copy_to_user(data, str, size);
    // 及时更新文件偏移值
    *offset += size - size_no_copy;
    return size - size_no_copy;
}

static ssize_t custom_module_timer_step_proc_write(struct file *file, const char __user *data, size_t len, loff_t *offset)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    char str[CUSTOM_MODULE_STR_LEN] = {0};
    int size_no_copy = copy_from_user(str, data, len);
    unsigned long res;
    int ret = kstrtoul(str, 10, &res);
    if (ret == -ERANGE) {
        printk(KERN_ERR "[%s][%d]str %s overflow\n", __func__, __LINE__, str);
    } else if (ret == -EINVAL) {
        printk(KERN_ERR "[%s][%d]str %s parsing error\n", __func__, __LINE__, str);
    } else {
        d->timer_step = res;
    }
    *offset += len - size_no_copy;
    return len - size_no_copy;
}

static struct proc_ops timer_step_proc_ops = {
    .proc_open = custom_module_proc_open,
    .proc_release = custom_module_proc_close,
    .proc_read = custom_module_timer_step_proc_read,
    .proc_write = custom_module_timer_step_proc_write,
}; 
// poll_maxsize
static ssize_t custom_module_poll_maxsize_proc_read(struct file *file, char __user *data, size_t len, loff_t *offset)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    char str[CUSTOM_MODULE_STR_LEN] = {0};
    int size = sprintf(str, "%u\n", d->poll_maxsize);    
    // 需要对当前文件偏移做判断，因为cat命令会循环调用read直到返回0
    if (*offset >= size) {
        return 0;
    }
    int size_no_copy = copy_to_user(data, str, size);
    // 及时更新文件偏移值
    *offset += size - size_no_copy;
    return size - size_no_copy;
}

static ssize_t custom_module_poll_maxsize_proc_write(struct file *file, const char __user *data, size_t len, loff_t *offset)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    char str[CUSTOM_MODULE_STR_LEN] = {0};
    int size_no_copy = copy_from_user(str, data, len);    
    unsigned long res;
    int ret = kstrtoul(str, 10, &res);
    if (ret == -ERANGE) {
        printk(KERN_ERR "[%s][%d]str %s overflow\n", __func__, __LINE__, str);
    } else if (ret == -EINVAL) {
        printk(KERN_ERR "[%s][%d]str %s parsing error\n", __func__, __LINE__, str);
    } else {
        d->poll_maxsize = res;
    }
    *offset += len - size_no_copy;
    return len - size_no_copy;
}

static struct proc_ops poll_maxsize_proc_ops = {
    .proc_open = custom_module_proc_open,
    .proc_release = custom_module_proc_close,
    .proc_read = custom_module_poll_maxsize_proc_read,
    .proc_write = custom_module_poll_maxsize_proc_write,
}; 


static int custom_module_create_proc(void)
{
    int ret;
    g_private_data.proc.proc_dir = proc_mkdir(g_private_data.module_name, NULL);
    if (!g_private_data.proc.proc_dir) {
        printk(KERN_ERR "[%s][%d]unable to create proc dir %s\n", __func__, __LINE__, g_private_data.module_name);
        ret = -ENOENT;
        goto PROC_DIR_ERR;
    }

    g_private_data.proc.memory_size_proc_file = proc_create("memory_size", 0644, g_private_data.proc.proc_dir, &memorysize_proc_ops);
    if (!g_private_data.proc.memory_size_proc_file) {
        printk(KERN_ERR "[%s][%d]unable to create proc memory_size_proc_file\n", __func__, __LINE__);
        ret = -ENOENT;
        goto PROC_MEMORY_SIZE_ERR;
    }

    g_private_data.proc.running_delayms_proc_file = proc_create("running_delayms", 0644, g_private_data.proc.proc_dir, &running_delayms_proc_ops);
    if (!g_private_data.proc.running_delayms_proc_file) {
        printk(KERN_ERR "[%s][%d]unable to create proc running_delayms_proc_file\n", __func__, __LINE__);
        ret = -ENOENT;
        goto PROC_RUNNING_DELAYMS_ERR;
    }

    g_private_data.proc.timer_step_proc_file = proc_create("timer_stepms", 0644, g_private_data.proc.proc_dir, &timer_step_proc_ops);
    if (!g_private_data.proc.timer_step_proc_file) {
        printk(KERN_ERR "[%s][%d]unable to create proc timer_step_proc_file\n", __func__, __LINE__);
        ret = -ENOENT;
        goto PROC_TIMER_STEP_ERR;
    }

    g_private_data.proc.poll_maxsize_proc_file = proc_create("poll_maxsize", 0644, g_private_data.proc.proc_dir, &poll_maxsize_proc_ops);
    if (!g_private_data.proc.poll_maxsize_proc_file) {
        printk(KERN_ERR "[%s][%d]unable to create proc poll_maxsize_proc_file\n", __func__, __LINE__);
        ret = -ENOENT;
        goto PROC_POLL_MAXSIZE_ERR;
    }
    
    return 0;
PROC_POLL_MAXSIZE_ERR:
    proc_remove(g_private_data.proc.timer_step_proc_file);
PROC_TIMER_STEP_ERR:
    proc_remove(g_private_data.proc.running_delayms_proc_file);
PROC_RUNNING_DELAYMS_ERR:
    proc_remove(g_private_data.proc.memory_size_proc_file);
PROC_MEMORY_SIZE_ERR:
    proc_remove(g_private_data.proc.proc_dir);
PROC_DIR_ERR:
    return ret;
}

static void custom_module_destroy_proc(void)
{
    proc_remove(g_private_data.proc.poll_maxsize_proc_file);
    proc_remove(g_private_data.proc.timer_step_proc_file);
    proc_remove(g_private_data.proc.running_delayms_proc_file);
    proc_remove(g_private_data.proc.memory_size_proc_file);
    proc_remove(g_private_data.proc.proc_dir);
}
/* proc end */

/* file_operations start */
static int custom_module_open(struct inode *inode, struct file *file)
{
    printk("[%s][%d]flag:%u mode:%u\n", __func__, __LINE__, file->f_flags, file->f_mode);
    g_private_data.isPauseControlThread = false;
    wake_up(&g_private_data.waitqueue_timer);
    file->private_data = &g_private_data;
    return 0;
}

static int custom_module_close(struct inode *node, struct file *file)
{
    printk("[%s][%d]\n", __func__, __LINE__);
    custom_module_data *d = (custom_module_data*)file->private_data;
    // 释放fasync_struct结构体
    fasync_helper(-1, file, 0, &d->fapp);
    g_private_data.isPauseControlThread = true;
    return 0;
}

static loff_t custom_module_lseek(struct file *file, loff_t offset, int flags)
{
    /* 如果应用层使用lseek系统调用，则应用层offset传递的是32bit的值，到内核这里，会变成64bit，高位会添加随机值 */
    offset = (loff_t)(s32)offset;
    custom_module_data *d = (custom_module_data*)file->private_data;
    switch (flags) {
        case SEEK_SET:
            if (d->memory_size < offset) {
                printk(KERN_ERR "[%s][%d]offset %lu is bigger than maxSize %llu\n", __func__, __LINE__, offset, d->memory_size);
                return -ENOMEM;
            }
            file->f_pos = offset;
            break;
        case SEEK_CUR:
            if (d->memory_size - file->f_pos < offset) {
                printk(KERN_ERR "[%s][%d]offset %lu is bigger than maxSize %llu\n", __func__, __LINE__, offset, d->memory_size - file->f_pos);
                return -ENOMEM;
            }
            file->f_pos += offset;            
            break;
        case SEEK_END:
            if (d->memory_size < offset) {
                printk(KERN_ERR "[%s][%d]offset %lu is bigger than maxSize %llu\n", __func__, __LINE__, offset, d->memory_size);
                return -ENOMEM;
            }
            file->f_pos = d->memory_size - offset;
            break;
        default:
            printk(KERN_ERR "[%s][%d]unsopport lseek flags\n", __func__, __LINE__);
            return -EINVAL;
    }

    printk("[%s][%d]device offset %llu\n", __func__, __LINE__, file->f_pos);
    return file->f_pos;
}

// read,write共用一个文件偏移量offset，其指向struct file -> f_pos
static ssize_t custom_module_read(struct file *file, char __user *data, size_t len, loff_t *offset)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    printk("[%s][%d]start offset %lu\n", __func__, __LINE__, *offset);
    if (*offset >= d->memory_size) {
        printk(KERN_ERR "[%s][%d]read at the end of memory\n", __func__, __LINE__);
        return -ENOMEM;
    }
    unsigned long long maxSize = d->memory_size - *offset;
    unsigned long size = maxSize > len ? len : maxSize;
    unsigned long size_no_copy = copy_to_user(data, d->memory + *offset, size);
    unsigned long read_length = size - size_no_copy;
    *offset += read_length;
    printk("[%s][%d]end offset %lu\n", __func__, __LINE__, *offset);

    printk("[%s][%d]read %llu bytes\n", __func__, __LINE__, read_length);
    return read_length;
}

static ssize_t custom_module_write(struct file *file, const char __user *data, size_t len, loff_t *offset)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    printk("[%s][%d]start offset %lu\n", __func__, __LINE__, *offset);
    if (*offset >= d->memory_size) {
        printk(KERN_ERR "[%s][%d]write at the end of memory\n", __func__, __LINE__);
        return -ENOMEM;
    }
    unsigned long long maxSize = d->memory_size - *offset;
    unsigned long size = maxSize > len ? len : maxSize;
    unsigned long size_no_copy = copy_from_user(d->memory + *offset, data, size);
    unsigned long write_length = size - size_no_copy;
    *offset += write_length;
    printk("[%s][%d]end offset %lu\n", __func__, __LINE__, *offset);

    printk("[%s][%d]write %llu bytes\n", __func__, __LINE__, write_length);
    return write_length;
}

// arg：用户空间传递过来的地址，需要进行用户态到内核态的转化
static long custom_module_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    
    switch (cmd) {
        case CUSTOM_MODULE_IOCTL_GET_SIZE_CMD:            
            if (put_user(d->memory_size, (unsigned long long*)arg)) {
                printk(KERN_ERR "[%s][%d]put_user failed\n", __func__, __LINE__);
                return -EFAULT;
            }            
            break;
        case CUSTOM_MODULE_IOCTL_SET_TIMER:
            if (get_user(d->isStartTimer, (bool*)arg)) {
                printk(KERN_ERR "[%s][%d]get_user failed\n", __func__, __LINE__);
                return -EFAULT;
            }
            break;
        case CUSTOM_MODULE_IOCTL_KILL:
        /*  fp：要操作的 fasync_struct。
            sig：要发送的信号。
            band：可读时设置为 POLL_IN，可写时设置为 POLL_OUT。
        */
            kill_fasync(&d->fapp, SIGIO, POLL_IN);
            printk("[%s][%d]\n", __func__, __LINE__);
            break;
        default:
            printk(KERN_ERR "[%s][%d]unsopport ioctl cmd\n", __func__, __LINE__);
            return -EINVAL;
    }
    printk("[%s][%d]execute cmd %u\n", __func__, __LINE__, cmd);
    return 0;
}

// vm：用户空间虚拟地址
static int custom_module_mmap(struct file *file, struct vm_area_struct *vm)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    unsigned long size = vm->vm_end - vm->vm_start;
    // 将内核空间的虚拟地址转化为物理地址，需要linux/io.h
    unsigned long page = virt_to_phys(d->memory) >> PAGE_SHIFT;
    // 将物理地址映射到用户空间地址
    int ret = remap_pfn_range(vm, vm->vm_start, page, size, PAGE_SHARED);
    if (ret) {
        printk(KERN_ERR "remap userspace %lu from physicalspace %lu over size %lu failed.ret=%d\n", 
            vm->vm_start, page, size, ret);
        return ret;
    }
    return 0;
}

static __poll_t custom_module_poll(struct file *file, struct poll_table_struct *poll_table)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    poll_wait(file, &d->waitqueue_poll, poll_table);
    return POLL_IN;
}

static int custom_module_fasync(int fd, struct file *file, int on)
{
    custom_module_data *d = (custom_module_data*)file->private_data;
    // 初始化fasync_struct结构体
    if (fasync_helper(fd, file, on, &d->fapp) < 0) {
        printk(KERN_ERR "[%s][%d]init fasync_struct failed\n", __func__, __LINE__);
        return -EIO;
    }
    return 0;
}

static const struct file_operations fops = {
    .llseek = custom_module_lseek,
    .read = custom_module_read,
    .write = custom_module_write,
    .unlocked_ioctl = custom_module_ioctl,
    .open = custom_module_open,
    .release = custom_module_close,
    .mmap = custom_module_mmap,
    .poll = custom_module_poll,
    .fasync = custom_module_fasync,
};
/* file_operations end */

static void custom_module_timer_callback(struct timer_list *timer)
{
    struct tm tm;
    struct timespec64 ts;
    ktime_get_real_ts64(&ts);
    time64_to_tm(ts.tv_sec, 0, &tm);
    memset(g_private_data.memory, 0, g_private_data.poll_maxsize);
    sprintf(g_private_data.memory, "Date: %04d-%02d-%02d %02d:%02d:%02d\n",
       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
       tm.tm_hour, tm.tm_min, tm.tm_sec);
    wake_up(&g_private_data.waitqueue_poll);
    mod_timer(timer, jiffies + msecs_to_jiffies(g_private_data.timer_step));
    printk("[%s][%d]timer running\n", __func__, __LINE__);
}

static int custom_module_control_thread(void *data)
{
    custom_module_data *d = (custom_module_data*)data;
    while (!kthread_should_stop()) {
        // 使用等待队列进行分支判断，如果满足条件，则继续执行；如果不满足条件，则阻塞当前线程的执行
        wait_event(d->waitqueue_timer, !d->isPauseControlThread);
        if (d->isStartTimer) {
            if (!timer_pending(&d->timer)) {                
                printk("[%s][%d]setup timer into timer_list\n", __func__, __LINE__);
                mod_timer(&d->timer, jiffies + msecs_to_jiffies(g_private_data.timer_step));
            }
        } else {
            if (timer_pending(&d->timer)) {                    
                // 删除定时器，同步等待回调完成
                del_timer_sync(&d->timer);
                printk("[%s][%d]delete timer from timer_list\n", __func__, __LINE__);
            }
        }
        msleep(g_private_data.running_delayms);
        /*if (d->isPauseControlThread) {
            printk("[%s][%d]control thread now pausing\n", __func__, __LINE__);
            msleep(CUSTOM_MODULE_PAUSE_DELAY_MS);
        } else {
            if (d->isStartTimer) {
                if (!timer_pending(&d->timer)) {
                    printk("[%s][%d]setup timer into timer_list\n", __func__, __LINE__);
                    mod_timer(&d->timer, jiffies + msecs_to_jiffies(g_private_data.timer_step));
                }
            } else {
                if (timer_pending(&d->timer)) {                    
                    // 删除定时器，同步等待回调完成
                    del_timer_sync(&d->timer);
                    printk("[%s][%d]delete timer from timer_list\n", __func__, __LINE__);
                }
            }
            msleep(g_private_data.running_delayms);
        }*/
    }
    return 0;
}

static void custom_module_stop_control_thread(void)
{
    del_timer(&g_private_data.timer);
    // 先开启暂停的线程，再停止线程
    g_private_data.isPauseControlThread = false;
    // 唤醒所有等待队列
    wake_up_all(&g_private_data.waitqueue_poll);
    wake_up_all(&g_private_data.waitqueue_timer);
    // 线程的结束，再也不能被唤醒
    kthread_stop(g_private_data.control_thread);
}

static int __init custom_module_init(void)
{   
    int ret;
    g_private_data.memory_size = 1 * 1024 * 1024;
    g_private_data.running_delayms = 100;
    g_private_data.timer_step = 500;
    g_private_data.poll_maxsize = 64;

    printk("[%s][%d]register char device\n", __func__, __LINE__);    
    g_private_data.isPauseControlThread = true;
    g_private_data.major = register_chrdev(0, g_private_data.module_name, &fops);
    if (!g_private_data.major) {
        printk(KERN_ERR "register_chrdev failed\n");
        ret = -ENODEV;
        goto REGISTER_ERR;
    } else {
        printk("[custom_module]:%s major:%d\n", g_private_data.module_name, g_private_data.major);
    }
    // kmalloc申请的是连续物理内存，不能大于128KB
    //g_private_data.memory = (char*)kzalloc(g_private_data.memory_size, GFP_KERNEL);
    g_private_data.memory = vzalloc(g_private_data.memory_size);
    if (!g_private_data.memory) {
        printk(KERN_ERR "[%s][%d]allocate global memory error\n", __func__, __LINE__);
        ret = -EFAULT;
        goto ALLOCATE_ERR;
    }    
    
    init_waitqueue_head(&g_private_data.waitqueue_poll);
    init_waitqueue_head(&g_private_data.waitqueue_timer);
    g_private_data.control_thread = kthread_run(custom_module_control_thread, &g_private_data, "control-thread");
    if (!g_private_data.control_thread) {
        printk(KERN_ERR "[%s][%d]create control thread failed\n", __func__, __LINE__);
        ret = -ESRCH;
        goto CREATE_KTHREAD_ERR;
    }
    // 初始化定时器数据结构，只用调用一次
    timer_setup(&g_private_data.timer, custom_module_timer_callback, 0);

    g_private_data.class = class_create(g_private_data.module_name);
    if (!g_private_data.class) {
        printk(KERN_ERR "[%s][%d]create class failed\n", __func__, __LINE__);
        goto CREATE_CLASS_ERR;
    }

    g_private_data.device = device_create(g_private_data.class, NULL, MKDEV(g_private_data.major, 0), NULL, g_private_data.module_name);
    if (!g_private_data.device) {
        printk(KERN_ERR "[%s][%d]create device failed\n", __func__, __LINE__);
        goto CREATE_DEVICE_ERR;
    }

    if (custom_module_create_proc()) {
        printk(KERN_ERR "[%s][%d]custom_module_create_proc error.\n", __func__, __LINE__);
        goto CREATE_PROC_ERR;
    }

    if (custom_module_sysfs_create()) {
        printk(KERN_ERR "[%s][%d]custom_module_sysfs_create error.\n", __func__, __LINE__);
        goto CREATE_SYSFS_ERR;
    }
    return ret;
CREATE_SYSFS_ERR:
    custom_module_destroy_proc();
CREATE_PROC_ERR:
    device_destroy(g_private_data.class, MKDEV(g_private_data.major, 0));
CREATE_DEVICE_ERR:
    class_destroy(g_private_data.class);
CREATE_CLASS_ERR:
    custom_module_stop_control_thread();
CREATE_KTHREAD_ERR:
    vfree(g_private_data.memory);
ALLOCATE_ERR:
    unregister_chrdev(g_private_data.major, g_private_data.module_name);
REGISTER_ERR:
    return ret;
    return 0;
}

static void __exit custom_module_exit(void)
{
    custom_module_sysfs_remove();
    custom_module_destroy_proc();
    device_destroy(g_private_data.class, MKDEV(g_private_data.major, 0));
    class_destroy(g_private_data.class);
    custom_module_stop_control_thread();
    vfree(g_private_data.memory);
    unregister_chrdev(g_private_data.major, g_private_data.module_name);
    printk("[%s][%d]unregister device\n", __func__, __LINE__);
}

module_init(custom_module_init);
module_exit(custom_module_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yujie Guo");
MODULE_DESCRIPTION("Custom Module for Learning");